iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
IT Operation

AWS 架構為什麼這樣選?30 天拆解服務選型與設計取捨系列 第 23 篇

Day 23|每個請求都要同步完成嗎?SQS、SNS 與 EventBridge 怎麼選?

  • 分享至 

  • xImage
  •  

上一篇比較了 ECS、EKS 與 Fargate,決定容器由誰管理、使用哪些運算資源,接下來帶大家看的主題是:當一個請求需要多個服務合作,哪些工作必須當下完成?

例如使用者下單後,系統需要建立訂單、保留庫存、寄送確認信與更新報表,如果全部同步處理,寄信服務變慢也會拖長下單時間;某個下游服務故障,還可能讓整個請求失敗。

今天會比較 Amazon SQS、Amazon SNS 與 Amazon EventBridge,看看佇列(Queue)、發布/訂閱(Pub/Sub)與事件路由(Event Routing)分別適合什麼情境。


哪些結果需要立即知道?

以下用一個假設的購物網站來看,在本文的業務規則下:

  • 訂單建立、庫存保留成功,才能顯示下單成功。
  • 確認信可以在一分鐘內寄出。
  • 分析報表允許延後五分鐘更新。

因此,系統必須先確認庫存保留與訂單建立成功,才能回覆使用者「下單成功」,確認信與報表則可以交給背景程式處理,使用者不必留在頁面上等待。

選擇同步或非同步時,可以先問:這項工作的結果,是否必須在這一次請求內確認,才能決定要回覆使用者什麼?

這個案例中需要立即知道訂單是否成立,但不需要等確認信寄出,才能完成下單流程。


傳出去的是工作指令,還是事件?

服務之間傳送的訊息,可以先分成兩種意思:

訊息 表達的意思
GenerateOrderPDF 請背景程式產生訂單 PDF
OrderCreated 訂單已經成立,讓需要知道的服務自行處理

前者是 Command(工作指令),送出端已經決定要執行什麼工作,後者是 Event(事件),描述已經發生的事情,後續行為由接收端決定。

如果需要把工作排隊交給背景程式,SQS 很適合;如果希望發布事件,讓下游透過訂閱或路由條件取得,再評估 SNS 或 EventBridge。

這個是訊息設計上的差異,而不是服務限制,SQS 同樣可以保存事件,承接 SNS 或 EventBridge 傳來的消息。


SQS:用佇列(Queue)讓工作排隊處理

假設使用者要求產生一份訂單 PDF,處理需要十秒:

處理方式 API 做什麼? 使用者取得什麼?
同步 等待 PDF 產生後才回應 完成的檔案
非同步 將工作送入佇列後回應 工作編號,稍後查詢結果

Amazon SQS(Simple Queue Service) 負責保存待處理訊息,讓背景程式依自己的能力取出工作。

送出訊息的程式稱為 Producer(生產者),取得訊息並執行工作的程式稱為 Consumer(消費者),背景工作程式也常稱為 Worker。

例如 API 將以下工作放進 SQS:

{
  "jobId": "JOB-1001",
  "action": "GenerateOrderPDF",
  "orderId": "ORD-5001"
}

背景程式取出訊息、產生 PDF,再更新工作狀態,API 不需要等待整份檔案完成,背景程式短暫停止時,已送入佇列的工作也能在保留期限內等待後續處理。

佇列可以緩衝流量,但不會增加處理能力

假設促銷期間,十秒內每秒進來 2,000 件工作,背景程式每秒只能完成 500 件,這段時間就會累積約 15,000 件工作。

SQS 可以先保存這些工作,讓消費者逐步消化,這種做法稱為 Load Leveling(負載平滑)。

但如果流入速度長期高於處理速度,等待時間仍會持續增加,因此除了監控訊息數量,也要看最舊訊息已經等了多久,以及是否需要增加消費者。

收到訊息後,成功處理才刪除

消費者取得訊息後,訊息會進入 Visibility Timeout(可見性逾時),通常會暫時對其他消費者不可見,工作成功後才刪除訊息;若程式中斷、未完成刪除,逾時後訊息就能再次被取出。

本文先以 Standard Queue(標準佇列) 為例:它採至少一次傳遞,不保證嚴格順序,即使在可見性逾時期間,仍可能重複傳遞訊息。

例如同一份 PDF 工作收到兩次,可以透過 jobId 唯一性限制或可靠的狀態更新機制,避免建立重複結果,這種重複執行仍不造成額外業務影響的設計,稱為 Idempotency(冪等性)。


SNS:用發布/訂閱(Pub/Sub)讓多個服務各自收到消息

如果訂單成立後,寄信、物流與分析服務都需要收到通知,就需要一對多的分送方式。

讓三個服務共同讀同一個 SQS 佇列,是分攤工作,無法保證每個服務各收到一份。

這時可以使用 Amazon SNS(Simple Notification Service),發布者將訊息送到 Topic(主題),SNS 再傳送給符合訂閱條件的接收方,這就是 Publish/Subscribe(發布/訂閱,Pub/Sub)。

將一份訊息分送多個接收方,也稱為 Fan-out(扇出),如果各服務需要獨立排隊,可以讓每個服務各有一個 SQS 佇列,再訂閱同一個 SNS Topic:

同一個訂單主題的訂閱者 處理方式
寄信佇列 寄信程式取出訊息,寄送確認信
物流佇列 物流程式取出訊息,建立配送工作
分析佇列 分析程式取出訊息,更新統計

每個服務都有自己的工作進度與重試流程,寄信服務暫時停止時,物流服務仍能繼續處理自己的佇列。

在這個組合中,SNS 負責分送,SQS 負責讓各接收方依自己的速度處理,兩者可以搭配使用。


EventBridge:用事件路由(Event Routing)把事件送到對應服務

Amazon EventBridge 可以依事件來源、類型與內容,將事件送到對應目標,也能整合 AWS 服務、自訂應用程式與支援的 SaaS 事件。

這裡聚焦在 Event Bus(事件匯流排),例如訂單服務發布一筆事件:

{
  "source": "shop.orders",
  "detail-type": "OrderCreated",
  "detail": {
    "orderId": "ORD-5001",
    "amount": 12000
  }
}

接收方可以依不同條件取得事件:

事件條件 後續處理
訂單成立 寄送確認信
訂單成立且金額超過指定門檻 交給風險檢查服務
訂單取消 通知庫存服務釋放保留數量
所有訂單事件 送往分析服務

這就是 Event Routing(事件路由),即使目前只有訂單服務這一個來源,也可以使用 EventBridge,來源數量不是必要條件。

SNS 也能篩選,怎麼判斷?

SNS 的訂閱可以設定 Filter Policy(篩選政策),依訊息屬性或 JSON 訊息內容決定要接收哪些訊息,因此需要篩選不一定就要使用 EventBridge。

我會先比較以下條件:

判斷方向 優先評估
圍繞明確主題,將消息分送給訂閱者,且訂閱篩選已滿足需求 SNS
希望透過事件匯流排,統一管理依事件來源、類型與內容進行的路由 EventBridge

EventBridge 也適合整合應用程式、AWS 服務、SaaS 或跨帳號事件,SNS 同樣支援內容篩選與跨帳號存取,因此仍要依實際整合方式選擇,不能只靠單一功能區分。

接收端若需要獨立排隊與控制處理速度,兩者都可以搭配 SQS。


順序與失敗處理,也會影響選擇

如果同一筆訂單的訊息必須依序處理,可以評估 SQS FIFO,或 SNS FIFO 搭配 SQS FIFO,維持同一訊息群組內的順序。

EventBridge 的新版 Custom Event Bus 也支援 FIFO Subscriber(依序傳遞的訂閱者),可以維持同一事件群組內的發布順序。

這些機制維持的是訊息傳入的順序,不會自動修正來源端已經送錯順序的業務事件。

失敗處理則要分清楚兩個階段:

失敗發生在哪裡? 要處理的問題
訊息還沒成功送到接收端 SNS/EventBridge 的傳遞重試與 DLQ 設定
消費者已取得訊息,但工作失敗 程式重試、冪等性,以及 SQS 的 DLQ 設定

Dead-letter Queue(DLQ,死信佇列) 用來隔離符合失敗轉送條件的訊息,方便後續分析與重新處理,哪些失敗會送入 DLQ 取決於服務與設定,傳遞端的 DLQ 不一定能捕捉接收程式內部的業務處理失敗。

團隊仍要設定告警、查明原因,再決定如何重新處理,訊息成功送達也不等於寄信、出貨等業務工作已經完成,處理結果仍要由應用程式記錄。


放回需求,我會怎麼選?

需求 優先評估 需要承擔的管理責任
有明確工作需要排隊交給背景程式 SQS 處理速度、逾時、重試與冪等性
將消息發布到主題,讓訂閱者各自取得 SNS 訂閱與篩選設定、傳遞失敗處理
依事件條件路由,並整合不同事件來源與目標 EventBridge 事件格式、分流條件、權限與失敗處理
接收端需要自己的緩衝與處理速度 在 SNS/EventBridge 後搭配 SQS 各佇列的積壓、消費速度與重試流程

回到開頭的購物網站,如果訂單服務已經明確決定「請寄信程式寄送確認信」,可以優先評估 SQS 保存這項背景工作。

在「訂單與庫存必須先確認、確認信可延後一分鐘,而且寄信是明確指定的背景工作」的條件下選擇 SQS,同時需承擔可靠發布、重試、冪等性與等待時間監控的責任。

如果希望訂單服務只發布 OrderCreated,由下游自行決定後續行為,即使目前只有一個接收方,也可以使用 SNS 或 EventBridge,再依主題訂閱、事件路由與整合需求比較。

SQS、SNS 與 EventBridge 其實沒有固定的升級順序 ,評估架構時要先確認訊息要交給誰、如何分送,以及接收端是否需要排隊,再決定服務與組合方式。


下一篇

當網路、資料庫、容器與訊息服務逐漸增加,每套環境都靠 Console 手動建立,很容易出現遺漏與設定差異。

下一篇會進入 Infrastructure as Code(IaC,基礎設施即程式碼),看看如何共用架構定義、明確管理環境差異,並讓每次變更都能審查與追蹤。

參考資料


上一篇
Day 22|容器上 AWS:ECS、EKS 與 Fargate 怎麼選?
系列文
AWS 架構為什麼這樣選?30 天拆解服務選型與設計取捨 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言